#ifndef GX_UI_H
#define GX_UI_H

#include "LibGL/GxGLText.h"
#include "LibGL/GxMath3D.h"
#include "Basic/GxLibBasic.h"
#include "Windows/GxWinTimer.h"
#include "Windows/GxDrawing2D.h"
#include "LibGL/GxTextures.h"
#include "LibGL/OpenGL.h"

namespace GxRendering
{
	namespace UI
	{
		using GxWinGUI::Drawing::Bitmap;

		const int STR_NAME_LENGTH = 32;
		const float CURSOR_FREQUENCY = 0.5f;

		// enum types defination

		const int COLOR_LIGHTEN = 100;
		// Dash dot pattern in binary : 1010101010101010
		const int DASH_DOT_PATTERN = 43690 ;
		const int DASH_DOT_FACTOR = 1;

		// Border Styles
		const int BS_NONE = 0;
		const int BS_RAISED = 1;
		const int BS_LOWERED = 2;
		const int BS_FLAT_ = 3;

		// Shift States
		const int SS_SHIFT = 1;
		const int SS_CONTROL = 2;
		const int SS_ALT = 4;
		const int SS_CONTROL_AND_SHIFT = 3;
		const int SS_CONTROL_AND_ALT = 6;
		const int SS_BUTTONLEFT = 8;
		const int SS_BUTTONMIDDLE = 16;
		const int SS_BUTTONRIGHT = 32;

		//Control Types
		//Bit 32: Determines whether the control is a container.
		const int CT_CONTROL = 0;
		const int CT_CONTAINER = -1;
		const int CT_ENTRY = -2;
		const int CT_FORM = -4;
		const int CT_LABEL = 1 ;
		const int CT_BUTTON = 2;
		const int CT_CHECKBOX = 4;
		const int CT_RADIOBOX = 8;
		const int CT_TEXTBOX = 16;
		const int CT_IMETEXTBOX = 17;
		const int CT_SCROLLBAR = 32;
		const int CT_LISTBOX = 64;
		const int CT_PROGRESSBAR = 128;
		const int CT_MENU = 256;
		const int CT_MENU_ITEM = 512;
		const int CT_TOOL_BUTTON = 513;


		typedef int CONTROLTYPE;
		typedef int BORDERSTYLE;
		typedef unsigned char SHIFTSTATE; 

		//Clip Rect Stack
		const int MAX_CLIPRECT_STACK_SIZE = 32;

		//Combo box
		const int COMBOBOX_LIST_SIZE = 6;

		//ProgressBar Style
		const int PROGRESSBAR_STYLE_SMOOTH = 1;
		const int PROGRESSBAR_STYLE_NORMAL = 2;

		//Scrollbar Orientation
		const int SO_VERTICAL = 0;
		const int SO_HORIZONTAL = 1;

		const int SCROLLBAR_BUTTON_SIZE = 17;
		const int SCROLLBAR_MIN_PAGESIZE = 8;

		//Message Type defination
		const int MSG_UI_NOTIFY = 0;
		const int MSG_UI_CLICK = 1;
		const int MSG_UI_DBLCLICK = 2;
		const int MSG_UI_MOUSEDOWN = 3;
		const int MSG_UI_MOUSEUP = 4;
		const int MSG_UI_MOUSEMOVE = 5;
		const int MSG_UI_MOUSEENTER = 6;
		const int MSG_UI_MOUSELEAVE = 7;
		const int MSG_UI_MOUSEHOVER = 19;
		const int MSG_UI_KEYDOWN = 8;
		const int MSG_UI_KEYUP = 9;
		const int MSG_UI_KEYPRESS = 10;
		const int MSG_UI_CHANGED = 11;
		const int MSG_UI_RESIZE = 12;

		// this message(TopLayer Draw) is sent by Entry to notify controls to do some drawing above any other controls if necessary.
		const int MSG_UI_TOPLAYER_DRAW = 13;
		const int MSG_UI_MOUSEWHEEL = 14;
		// Form Messages
		const int MSG_UI_FORM_ACTIVATE = 15;
		const int MSG_UI_FORM_DEACTIVATE = 16;
		const int MSG_UI_FORM_SHOW = 17;
		const int MSG_UI_FORM_HIDE = 18;

		class UI_Base;


		void DrawCircleLine(vec2 pos, float r, float digit, float ang1, float ang2);

		

		struct UI_MsgArgs
		{
			UI_Base *Sender;
			String Tags;
			int Type;
			void *Data;
			UI_MsgArgs()
			{
				Sender = NULL;
				Data = NULL;
				Type = -1;
			};
		};

		struct Color
		{
			unsigned char R,G,B,A;
			Color(){R=G=B=0; A = 0;};
			Color(unsigned char AR,unsigned char AG,unsigned char AB,unsigned char AA){R=AR;G=AG;B=AB;A=AA;};
			Color(unsigned char AR,unsigned char AG,unsigned char AB){R=AR;G=AG;B=AB;A=255;};
			Color(COLORREF c){R=GetRValue(c); G=GetGValue(c); B=GetBValue(c); A=255;};
		};

		struct UIMouseEventArgs
		{
			int X, Y;
			int Delta;
			SHIFTSTATE Shift;
		};

		struct UIKeyEventArgs
		{
			unsigned short Key;
			SHIFTSTATE Shift;
		};

		typedef Event<UI_Base *> NotifyEvent;
		typedef Event<UI_Base *, UIMouseEventArgs &> MouseEvent;
		typedef Event<UI_Base *, UIKeyEventArgs &> KeyEvent;

		struct Rect
		{
			int x,y,h,w;
			Rect()
			{
				x=y=h=w=0;
			}
			Rect(int ax,int ay, int aw, int ah)
			{
				x=ax;y=ay;h=ah;w=aw;
			}
		};

		class Graphics
		{
		public:
			static Color PenColor, SolidBrushColor;
			static Color GradiantBrushColor1, GradiantBrushColor2;
			static Color GradiantBrushColor3, GradiantBrushColor4;
			static void DrawArc(int x, int y, int rad, float theta, float theta2);
			static void DrawRectangle(int x1, int y1, int x2, int y2);
			static void FillRectangle(int x1, int y1, int x2, int y2, bool gradiant = false);
			static void DrawRoundRect(int x1, int y1, int x2, int y2, int rad);
			static void FillRoundRect(int x1, int y1, int x2, int y2, int rad, bool gradiant = false);
			static void DrawLine(int x1, int y1, int x2, int y2);
		};

		class ColorTable
		{
		public:
			Color ControlBackColor;
			Color ControlBorderColor;
			Color ToolButtonBorderHighLight;
			Color ToolButtonBorderSelected;
			Color ToolButtonBackColor1;
			Color ToolButtonBackColor2;
			Color ToolButtonBackColorHighlight1;
			Color ToolButtonBackColorHighlight2;
			Color ToolButtonBackColorPressed1;
			Color ToolButtonBackColorPressed2;
			Color ToolButtonBackColorChecked1;
			Color ToolButtonBackColorChecked2;
			Color ToolButtonSeperatorColor;
			Color ButtonBackColorChecked;
			Color StatusStripBackColor1;
			Color StatusStripBackColor2;
			Color StatusStripBackColor3;
			Color StatusStripBackColor4;
			Color MenuItemForeColor;
			Color MenuItemHighlightForeColor;
			Color MenuItemDisabledForeColor;
			Color MemuIconBackColor;
			Color MenuBackColor;
			Color MenuBorderColor;
			Color MenuSeperatorColor;
			Color TabPageBorderColor;
			Color TabPageItemBackColor1, TabPageItemBackColor2;
			Color TabPageItemSelectedBackColor1, TabPageItemSelectedBackColor2;
			Color TabPageItemHighlightBackColor1, TabPageItemHighlightBackColor2;
		};

		ColorTable * CreateDefaultColorTable();
		
		class ClipRectStack
		{
		protected:
			Rect Buffer[MAX_CLIPRECT_STACK_SIZE];
		public:
			ClipRectStack();
			~ClipRectStack();
		public:
			int StackSize;
			int WindowWidth,WindowHeight;
			void PushRect(Rect nRect);
			Rect PopRect();
			Rect GetTop();
			void AddRect(Rect nRect);//this function will calculate the intersection with the top of the stack and push it into the stack. It will automatically call the PushRect function.
			void Clear();
		};

		class UIEntry;
		class Container;
		class Label;

		class Global
		{
		private:
			static bool intialized;
		public:
			static int EventGUID;
			static ClipRectStack * ClipRects;
			static int CursorPosX, CursorPosY;
			static UI_Base * PointedComponent; // Component under cursor
			static UIEntry * Entry;
			static int Width, Height;
			static int HoverTimeThreshold;
			static RefPtr<UI::ColorTable> ColorTable;
			static Label * CheckmarkLabel;
			static void Init();
			static void Finalize();
			static void MakeCurrent(UIEntry * entry);
		};

		class UI_Base : public Object
		{
		public:
			virtual void HandleMessage(const UI_MsgArgs *Args);
		};

		enum Cursor
		{
			Arrow, Cross, IBeam, Wait, SizeNS, SizeWE, SizeNESW, SizeNWSE, SizeAll
		};

		class Control : public UI_Base
		{
			friend Container;
			friend UIEntry;
		protected:
			int EventID; // Used by Containers to avoid message resending;
		protected:
			GxWinGUI::Timer tmrHover;
			Rect clientRect;
			bool CaptureMouse;
			bool LastInClient;
			bool TopMost;
			int Height,Width;
			bool DownInRect;
			bool IsPointInClient(int X, int Y);
			void HoverTimerTick(Object * sender, GxWinGUI::EventArgs e);
		public:
			Control();
			~Control();
		public:
			UI::Cursor Cursor;
			String Name;
			int ID;
			CONTROLTYPE Type;
			Control *Parent;
			int  Left,Top;
			bool BackgroundShadow;
			bool Enabled,Visible,Focused,TabStop, GenerateMouseHoverEvent;
			Color BackColor,FontColor,BorderColor;
			BORDERSTYLE BorderStyle;
			int AbsolutePosX; int AbsolutePosY;
			void SetName(String AName);
			void Posit(int ALeft, int ATop, int AWidth, int AHeight);
			void SetHeight(int val);
			void SetWidth(int val);
			int GetHeight();
			int GetWidth();
			Rect ClientRect();
			virtual void SizeChanged();
			virtual void Draw(int absX, int absY);
		public:
			UIEntry * GetEntry();
		public:
			enum _DockStyle
			{
				dsNone, dsTop, dsBottom, dsLeft, dsRight, dsFill
			};
		public:
			_DockStyle DockStyle;
			NotifyEvent OnClick;
			NotifyEvent OnDblClick;
			NotifyEvent OnChanged;
			NotifyEvent OnResize;
			NotifyEvent OnMouseEnter;
			NotifyEvent OnMouseLeave;
			NotifyEvent OnMouseHover;
			NotifyEvent OnLostFocus;
			MouseEvent OnMouseDown;
			MouseEvent OnMouseMove;
			MouseEvent OnMouseUp;
			MouseEvent OnMouseWheel;
			KeyEvent   OnKeyDown;
			KeyEvent   OnKeyUp;
			KeyEvent   OnKeyPress;
			//Message
			void BroadcastMessage(const UI_MsgArgs *Args);
			//Event Reactions
			virtual void DoMouseMove(int X, int Y);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseEnter(int X, int Y);
			virtual void DoMouseLeave(int X, int Y);
			virtual void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyUp(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyPress(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoMouseHover();
			virtual void DoClick();
			virtual void DoDblClick();
			virtual void SetFocus();
			virtual bool ContainsFocus();
			virtual void LostFocus();
			virtual void DoClosePopup();
		};

		class Container: public Control
		{
		protected:
			
		public:
			Container();
			~Container();
		public:
			Array<RefPtr<Control> > Controls;
			Array<Control *> TabList;
			int Margin;
			void AddChild(Control *nControl);
			void RemoveChild(Control *AControl);
			void MoveFocus(Control *AControl);
			void MoveFocusNext();
			void ClearControlFocus();
			virtual bool ContainsFocus();
			virtual void ArrangeControls();
			virtual void SetAlpha(unsigned char Alpha);
			virtual void InternalBroadcastMessage(UI_MsgArgs *Args);
			virtual void DoDblClick();
			virtual void DoMouseMove(int X, int Y);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseLeave(int X, int Y);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyUp(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyPress(unsigned short Key, SHIFTSTATE Shift);
			virtual void Draw(int absX,int absY);
			virtual void SetFocusedControl(Control *Target);
			virtual void SizeChanged();
			virtual void DoClosePopup();
		};

		struct FormStyle 
		{
			Color TitleBarColors[4];
			Color TitleBarDeactiveColors[4];
			Color TitleBarFontColor;
			bool ShowIcon;
			Color CtrlButtonBackColor;
			Font TitleFont;
			int CtrlButtonBorderStyle;
			int TitleBarHeight;
			bool TopMost;
			bool Modal;
		};

		class Label;
		class Button;

		class MainMenu;
		class Form : public Container
		{
		protected:
			bool DownInTitleBar;
			bool DownInButton;
			int DownPosX,DownPosY;
			Control *btnClose;
			Label *lblClose;
			Label *lblTitle;
			String Text; 
			FormStyle formStyle;
			void FormStyleChanged();
		public:
			Form();
			~Form();
		public:
			
			NotifyEvent OnShow;
			NotifyEvent OnClose;

			bool CanResize;
			bool ButtonClose;
			bool Activated;
			
			void SetText(String AText);
			String GetText();
			int GetClientHeight();
			int GetClientWidth();
			void SetFormStyle(const FormStyle & FormStyle);

			virtual void DoMouseMove(int X, int Y);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void Draw(int absX,int absY);
			virtual void SizeChanged();
			virtual void SetAlpha(unsigned char Alpha);
		};

		class Label: public Control
		{
		protected:
			String FCaption;
			bool FChanged;
		public:
			RefPtr<GLText> Text;
			Label();
			~Label();
		public:
			Color ShadowColor;
			bool DropShadow;
			bool AutoSize, MultiLine;
			void SetText(const String & text);
			void UpdateText();
			String GetText();
			void SetFont(Font AFont);
			virtual void Draw(int absX, int absY);
			virtual void SizeChanged();
		};

		class Button: public Label
		{
		protected:
			bool IsMouseDown;
		public:
			Button();
		public:
			bool Checked;
			Color FocusRectColor;
			virtual void Draw(int absX, int absY);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyUp(unsigned short Key, SHIFTSTATE Shift);
			
		};

		class CheckBox : public Label
		{
		protected:
			Label *lblCheck;
		public:
			CheckBox();
			~CheckBox();
		public:
			bool Checked;
			Color FocusRectColor;
			virtual void Draw(int absX, int absY);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
		};

		class RadioBox : public CheckBox
		{
		public:
			RadioBox();
		public:
			bool GetValue();
			void SetValue(bool AValue);
			virtual void Draw(int absX, int absY);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
		};

		class CustomTextBox : public Control
		{
		protected:
			__int64 Time,Freq;
			String FText;
			GLText *glText;
			int SelOrigin;
			bool Changed, KeyDown,SelectMode;
			int LabelOffset;
			int HitTest(int posX);
			void CursorPosChanged();
		public:
			CustomTextBox();
			~CustomTextBox();
		public:
			bool Locked;
			int TextBorderX,TextBorderY;
			int CursorPos,SelStart, SelLength;
			int AbsCursorPosX,AbsCursorPosY;
			Color SelectionColor,SelectedTextColor;
			const String GetText();
			void TextChanged();
			void SetText(const String & AText);
			void SetFont(Font AFont);
			void CopyToClipBoard();
			void PasteFromClipBoard();
			void DeleteSelectionText();
			void SelectAll();
 			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseMove(int X, int Y);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyUp(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyPress(unsigned short Key, SHIFTSTATE Shift);
			void DoInput(const String & AInput);
			virtual void Draw(int absX, int absY);
		};

		class TextBox : public CustomTextBox
		{
		public:
			virtual void  DoKeyPress(unsigned short Key, SHIFTSTATE Shift);
		};

		class IMETextBox : public TextBox
		{
		public:
			IMETextBox(){Type=CT_IMETEXTBOX;};
		};

		class IMEWindow : public Control
		{
		protected:
			Array<String> CandidateList;
			RefPtr<Label> lblIMEName, lblCompStr, lblCompReadStr;
			Array<RefPtr<Label>> lblCandList;
		public:
			IMEWindow();
			~IMEWindow();
		public:
			Control *Panel;
			int CursorPos,CandidateCount;
			int BorderWeight;
			int WindowWidth, WindowHeight;
			String strComp,strIME,strCompRead;
			bool ShowCandidate;
			void ChangeInputMethod(String AInput);
			void ChangeCompositionString(String AString);
			void ChangeCompositionReadString(String AString);
			void SetCandidateListItem(int Index, const TCHAR *Data);
			void SetCandidateCount(int Count);
			virtual void Draw(int absX, int absY);
		};

		class IMEHandler : public Object
		{
		public:
			IMEHandler();
			~IMEHandler();
		public:
			bool Enabled;
			CustomTextBox *TextBox;
			IMEWindow *IMEWindow;
			bool HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
			void StringInputed(String AString);
		};

		struct TopMostAreaInfo
		{
			Rect rect;
			Control * ctrl;
		};

		class UIEntry: public Container
		{
		protected:
			HWND formHandle;
			Array<TopMostAreaInfo> TopmostAreas;
			SHIFTSTATE GetCurrentShiftState();
			void TranslateMouseMessage(UIMouseEventArgs &Data,WPARAM wParam, LPARAM lParam);
			void DeactivateAllForms();
		public:
			UIEntry(int WndWidth, int WndHeight, HWND _formHandle = NULL);
			~UIEntry();
			GLText *glText;
		public:
			RefPtr<Label> CheckmarkLabel;
			RefPtr<ClipRectStack> ClipRects;
			Control *FocusedControl;
			IMEHandler *FIMEHandler;
			Form *ActiveForm;
			Array<RefPtr<Form>> Forms;
			HWND GetMainFormHandle()
			{
				return formHandle;
			}
			void BeginUIDrawing();
			void EndUIDrawing();
			void DrawUI();
			void AddForm(Form *NewForm);
			void RemoveForm(Form *Form);
			void ShowWindow(Form *Form);
			void CloseWindow(Form *Form);
			void RegisterTopMostWindow(Control * component, const Rect &rect);
			void UnregisterTopMostArea(Control * component);
			bool HandleSystemMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
			virtual void InternalBroadcastMessage(UI_MsgArgs *Args);
			virtual void SizeChanged();
			virtual void Draw(int absX,int absY);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyUp(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoKeyPress(unsigned short Key, SHIFTSTATE Shift);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseMove(int X, int Y);
			virtual void HandleMessage(const UI_MsgArgs *Args);
			
			void SetFocusedControl(Control *Target);
		};

		class ScrollBar: public Control
		{
		protected:
			bool DownInSlider;
			int OriPos;
			int DownPosX,DownPosY;
			int Orientation; // SO_VERTICAL or SO_HORIZONTAL
			int Position;
			int Max,Min;
			int PageSize;
			bool PointInSlider(int X, int Y);
			bool PointInFreeSpace(int X, int Y);
			void BtnIncClick(UI_Base * sender);
			void BtnDecClick(UI_Base * sender);
		public:
			ScrollBar();
			~ScrollBar();
		public:
			int SmallChange,LargeChange;
			Button *btnInc, *btnDec;
			Control *Slider;
			int GetOrientation();
			void SetOrientation(int NewOri);
			void SetValue(int AMin, int AMax, int APos);
			void SetMin(int AMin);
			void SetMax(int AMax);
			void SetPosition(int APos);
			int GetMin();
			int GetMax();
			int GetPosition();
			virtual void Draw(int absX, int absY);
			virtual void DoMouseMove(int X, int Y);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X,int Y, SHIFTSTATE Shift);
			virtual void HandleMessage(const UI_MsgArgs *Args);
			virtual void SizeChanged();
		};

		class ScrollBar2: public Control
		{
		protected:
			int tmrOrientation;
			GxWinGUI::Timer tmrTick;
			bool DownInSlider;
			int OriPos;
			int DownPosX,DownPosY;
			int Orientation; // SO_VERTICAL or SO_HORIZONTAL
			int Position;
			int Max,Min;
			int PageSize;
			bool PointInSlider(int X, int Y);
			bool PointInFreeSpace(int X, int Y);
			void BtnIncMouseDown(UI_Base * sender, UIMouseEventArgs & e);
			void BtnDecMouseDown(UI_Base * sender, UIMouseEventArgs & e);
			void BtnIncMouseUp(UI_Base * sender, UIMouseEventArgs & e);
			void BtnDecMouseUp(UI_Base * sender, UIMouseEventArgs & e);
			void tmrTick_Tick(Object * sender, GxWinGUI::EventArgs e);
		public:
			ScrollBar2();
			~ScrollBar2();
		public:
			int SmallChange,LargeChange;
			Button *btnInc, *btnDec;
			Control *Slider;
			int GetOrientation();
			void SetOrientation(int NewOri);
			void SetValue(int AMin, int AMax, int APos, int pageSize);
			void SetMin(int AMin);
			void SetMax(int AMax);
			void SetPosition(int APos);
			int GetMin();
			int GetMax();
			int GetPosition();
			virtual void Draw(int absX, int absY);
			virtual void DoMouseMove(int X, int Y);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X,int Y, SHIFTSTATE Shift);
			virtual void HandleMessage(const UI_MsgArgs *Args);
			virtual void SizeChanged();
		};

		class ListBox : public Control
		{
		protected:
			Font font;
			int HighLightID;
			int ItemHeight;
			bool Selecting;
			bool HotTrack;
			int SelOriX,SelOriY;
			int BorderWidth;
			bool DownInItem;
			ScrollBar *ScrollBar;
			void ListChanged();
			void SelectionChanged();
		public:
			ListBox();
			~ListBox();
		public:
			Array<RefPtr<Control>> Items;
			bool HideSelection, MultiSelect;
			Color SelectionColor,UnfocusedSelectionColor,SelectionForeColor,FocusRectColor,HighLightColor,HighLightForeColor;
			Array<Control *> Selection;
			int SelectedIndex;
			int Margin;
			int HitTest(int X, int Y);
			Control *GetSelectedItem();
			int GetItemHeight();
			Label *GetTextItem(int Index);
			CheckBox *GetCheckBoxItem(int Index);
			Control *GetItem(int Index);
			int AddTextItem(String Text);
			int AddCheckBoxItem(String Text);
			int AddControlItem(Control *Item);
			void SetFont(Font AFont);
			void Delete(int Index);
			void Delete(Control *Item);
			bool ItemInSelection(Control *Item);
		public:
			virtual void Draw(int absX, int absY);
			virtual void SizeChanged();
			virtual void HandleMessage(const UI_MsgArgs *Args);
			virtual void DoMouseDown(int x, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int x, int Y, SHIFTSTATE Shift);
			virtual void DoMouseMove(int x, int Y);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
		};

		class ComboBox : public ListBox
		{
		private:
			int lH,lW,lL,lT;
		protected:	
			int ListLeft,ListTop,ListHeight,ListWidth;
			
			int ButtonSize;
			bool ShowList;
			bool PosInList(int X, int Y);
			void ChangeSelectedItem(int id);
			void ToggleList(bool sl);
			void BeginListBoxFunctions();
			void EndListBoxFunctions();
		public:
			ComboBox();
			~ComboBox();
		public:
			TextBox *TextBox;
			Button *btnDrop;
			int ButtonWidth;
			void SetReadOnly(bool Val);
			bool GetReadOnly();
			virtual void Draw(int absX, int absY);
			virtual void SizeChanged();
			virtual void HandleMessage(const UI_MsgArgs *Args);
			virtual void DoMouseDown(int x, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int x, int Y, SHIFTSTATE Shift);
			virtual void DoMouseMove(int x, int Y);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void SetFocus();
			virtual void LostFocus();
			virtual void DoClosePopup();
		};

		class ProgressBar : public Control
		{
		protected:
			int Max,Position;
		public:
			Color ProgressBarColors[4];
			int Style;
			ProgressBar();
			~ProgressBar();
			void SetMax(int AMax);
			void SetPosition(int APos);
			int GetMax();
			int GetPosition();
			virtual void Draw(int absX, int absY);
		};

		class MenuItem;

		class Menu : public Container
		{
			friend MenuItem;
		private:
			static const int ItemHeight = 24;
			static const int Margin = 2;
		public:
			enum MenuStyle
			{
				msPopup, msMainMenu
			};
		private:
			Array<MenuItem*> Items;
			MenuStyle style;
		protected:
			MenuItem * parentItem;
			Menu * curSubMenu;
			void PositMenuItems();
			void ItemSelected(MenuItem * item); // Called by MenuItem
			void PopupSubMenu(Menu * subMenu, int x, int y); // Called by MenuItem
			void CloseSubMenu();
			int GetSelectedItemID();
		public:
			NotifyEvent OnPopup;
			NotifyEvent OnMenuClosed;
		public:
			void AddItem(MenuItem * item);
			void RemoveItem(MenuItem * item);
			int Count();
			MenuItem * GetItem(int id);
			void DrawPopup();
			void DrawMenuBar(int absX, int absY);
			void Draw(int absX, int absY);
			void Popup(int x, int y);
			void CloseMenu();
			void DoClosePopup();
			Menu(MenuStyle mstyle = msPopup);
			virtual void DoMouseMove(int X, int Y);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void HandleMessage(const UI_MsgArgs * Args);
			virtual void SetFocus();
		};

		class MenuItem : public Control
		{
			friend Menu;
		protected:
			wchar_t accKey;
			bool isButton;
			void ItemSelected(MenuItem * item); // Called by SubMenu
		private:
			bool cursorInClient;
			static const int Margin = 8;
			bool isSeperator;
			RefPtr<Label> lblText, lblShortcut;
			void Init();
		public:
			bool IsSeperator();
			bool Selected;
			bool Checked;
			String GetText();
			void SetText(const String & str);
			String GetShortcutText();
			void SetShortcutText(const String & str);
			RefPtr<Menu> SubMenu;
			void AddItem(MenuItem * item);
			void RemoveItem(MenuItem * item);
			MenuItem * GetItem(int id);
			wchar_t GetAccessKey();
			int Count();
			int MeasureWidth(bool isButton = false);
			MenuItem();
			MenuItem(const String & text);
			MenuItem(const String & text, const String & shortcutText);
			void DrawMenuItem(int absX, int absY, int width, int height);
			void DrawMenuButton(int width, int height);
			virtual void DoMouseEnter(int X, int Y);
			virtual void DoMouseLeave(int X, int Y);
			virtual void DoMouseHover();
			virtual void DoMouseMove(int X, int Y);
			virtual void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			virtual void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			virtual void DoKeyDown(unsigned short Key, SHIFTSTATE Shift);
			virtual void Draw(int absX, int absY);
			virtual void DoClick();
			virtual void HandleMessage(const UI_MsgArgs * Args);
			
		};

		class GrayScaleImageFilter
		{
		public:
			static Bitmap * Filter(Bitmap * bmp);
		};

		class Image : public Object
		{
		private:
			bool created;
			unsigned int texID;
			int width, height;
			float maxCoordX, maxCoordY;
		public:
			Image(Texture * tex);;
			Image(Bitmap * bmp, Color * transparentColor);
			~Image();
			unsigned int GetTextureID();
			int GetWidth();
			int GetHeight();
			void Replace(Bitmap * bmp, Color * transparentColor);
			void Draw(int x, int y, const Color & c);
			void Draw(int x, int y, int w, int h, const Color & c);
		};

		class ImageDisplay : public Container
		{
		private:
			RefPtr<Image> image;
		public:
			void SetImage(Image * img);
			Image * GetImage();
			void Draw(int absX, int absY);
			ImageDisplay();
		};

		class ToolStrip;

		class ToolButton : public Control
		{
			friend ToolStrip;
		public:
			enum _ButtonStyle
			{
				bsNormal, bsDropDown, bsSeperator
			};
		private:
			static const int Margin = 3;
			static const int DropDownButtonWidth = 12;
		private:
			RefPtr<Image> image, imageDisabled;
			String text;
			RefPtr<Label> lblText;
			ToolButton * bindButton;
			int mousePosX;
			void Init();
		public:
			ToolButton();
			ToolButton(const String & _text, _ButtonStyle bs, Bitmap * bmp, Color * transColor);
		public:
			bool Selected;
			bool Checked;
			bool Pressed;
			bool ShowText;
			_ButtonStyle ButtonStyle;
			String GetText();
			void BindButton(ToolButton * btn);
			void SetText(const String & _text);
			void Draw(int absX, int absY);
			int MeasureWidth();
			int MeasureHeight();
			void SetImage(Bitmap * bmp, Color * transColor=0);
			void DoMouseEnter(int X, int Y);
			void DoMouseLeave(int X, int Y);
			void DoMouseMove(int X, int Y);
			void DoMouseDown(int X, int Y, SHIFTSTATE shift);
			void DoMouseUp(int X, int Y, SHIFTSTATE shift);
		};

		class ToolStrip : public Control
		{
		public:
			enum ToolStripOrientation
			{
				Horizontal, Vertical
			};
		private:
			static const int LeftMargin = 4;
			static const int TopMargin = 2;
			
			Array<RefPtr<ToolButton>> buttons;
		protected:
			void PositButtons();
			virtual void SizeChanged();
		public:
			bool FullLineFill;
			bool ShowText;
			bool MultiLine;
			ToolStripOrientation Orientation;
			ToolStrip();
			ToolButton * AddButton(const String & text, Bitmap * bmp);
			ToolButton * AddButton(const String & text, Bitmap * bmp, Color * transColor);
			void AddSeperator();
			ToolButton * GetButton(int id);
			int Count();
			void Draw(int absX, int absY);
			void DoMouseMove(int X, int Y);
			void DoMouseDown(int X, int Y, SHIFTSTATE shift);
			void DoMouseUp(int X, int Y, SHIFTSTATE shift);
			void DoMouseLeave(int X, int Y);
		};

		class StatusPanel : public Control
		{
		public:
			enum _FillMode
			{
				Fill, Fixed, AutoSize
			};
		private:
			RefPtr<Label> text;
			void Init();
		public:
			_FillMode FillMode;
			StatusPanel();
			StatusPanel(const String & text, int width, _FillMode fm);
			void SetText(const String & text);
			String GetText();
			int MeasureWidth();
			void Draw(int absX, int absY);
		};

		class StatusStrip : public Control
		{
		private:
			
			Array<RefPtr<StatusPanel>> panels;
			void PositItems();
			
		public:
			int LeftMargin;
			int TopMargin;
			StatusStrip();
			void AddItem(StatusPanel * pannel);
			int Count();
			StatusPanel * GetItem(int id);
			void DoMouseMove(int X, int Y);
			void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			void Draw(int absX, int absY);
		};

		class TabPage;

		class TabControl : public Container
		{
		private:
			int highlightItem;
			int headerHeight;
			int MeasureHeight();
			void SetClient();
		protected:
			Array<RefPtr<TabPage>> pages;
		public:
			enum _TabStyle
			{
				tsText, tsImage, tsTextImage
			};
			enum _TabPosition
			{
				tpTop, tpBottom
			};
		public:
			bool CanClose, CanMove;
			_TabStyle TabStyle;
			_TabPosition TabPosition;
			int SelectedIndex;
			void AddItem(TabPage * page);
			void RemoveItem(TabPage * page);
			TabPage * GetItem(int id);
			TabPage * GetSelectedItem();
			void DoMouseMove(int X, int Y);
			void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
			void Draw(int absX, int absY);
			void SizeChanged();
			void SwitchPage(int id);
			int HitTest(int X, int Y);
			TabControl();
		};

		class TabPage : public Container
		{
		private:
			RefPtr<Label> text;
			RefPtr<Image> image;
			static const int LeftMargin = 4;
			static const int TopMargin = 6;
		public:
			void SetText(const String & text);
			String GetText();
			void SetImage(Bitmap * bitmap, Color * transparentColor=0);
			int MeasureWidth(TabControl::_TabStyle style);
			int MeasureHeight(TabControl::_TabStyle style);
			void DrawHeader(int x, int y, int h, TabControl::_TabStyle style);
			TabPage();
		};

		class GLView : public Control
		{
		private:
			Rect rect;
			unsigned int texID;
			RefPtr<RenderBuffer> rb;
			RefPtr<FrameBufferObject> fbo;
			void ResetFBO();
		public:
			NotifyEvent OnRender;
			void BeginDrawing();
			void EndDrawing();
			void Refresh();
			void SizeChanged();
			void Draw(int absX, int absY);
			GLView();
			~GLView();
		};

		class UpDown : public Control
		{
		private:
			RefPtr<Button> btnUp, btnDown;
			TextBox * text;
			int state;
			int ldY;
			float inc;
			GxWinGUI::Timer tmrHover;
			void tmrHoverTick(Object * sender, GxWinGUI::EventArgs e);
		public:
			UpDown(TextBox * txtBox, float _min, float _max, float minInc, float maxInc);
			int Digits;			
			float MinIncrement;
			float MaxIncrement;
			float Min, Max;
			void Draw(int absX, int absY);
			void DoMouseDown(int X, int Y, SHIFTSTATE Shift);
			void DoMouseMove(int X, int Y);
			void DoMouseUp(int X, int Y, SHIFTSTATE Shift);
		};
	}
}
#endif